package com.autumn.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.modelmapper.Converter;
import org.modelmapper.ModelMapper;
import org.modelmapper.PropertyMap;
import org.modelmapper.TypeMap;
import org.modelmapper.convention.MatchingStrategies;
import org.modelmapper.convention.NameTransformers;
import org.modelmapper.convention.NamingConventions;

import com.autumn.util.function.FunctionTwoAction;

/**
 * 提供 ModelMapper 帮助
 * 
 * @author 老码农
 *
 *         2017-11-17 11:26:46
 */
public class AutoMapUtils {

	private static final ModelMapper MODEL_MAPPER = new ModelMapper();

	static {
		MODEL_MAPPER.getConfiguration().setSourceNamingConvention(NamingConventions.JAVABEANS_ACCESSOR)
				.setDestinationNamingConvention(NamingConventions.JAVABEANS_MUTATOR)
				.setSourceNameTransformer(NameTransformers.JAVABEANS_ACCESSOR)
				.setDestinationNameTransformer(NameTransformers.JAVABEANS_MUTATOR)
				.setMatchingStrategy(MatchingStrategies.STRICT);
	}

	/**
	 * 转换(只是兼容老函数重载)
	 * 
	 * @param source
	 *            源
	 * @param targetClass
	 *            目标类型
	 * @return
	 */
	public static <Target> Target mapTo(Class<Target> targetClass, Object source) {
		if (source == null) {
			return null;
		}
		return MODEL_MAPPER.map(source, targetClass);
	}

	/**
	 * 转换
	 * 
	 * @param source
	 *            源对象
	 * @param destination
	 *            被赋值的对象
	 */
	public static void map(Object source, Object destination) {
		MODEL_MAPPER.map(source, destination);
	}

	/**
	 * 转换
	 * 
	 * @param source
	 *            源
	 * @param targetClass
	 *            目标类型
	 * @return
	 */
	public static <Target> Target map(Object source, Class<Target> targetClass) {
		if (source == null) {
			return null;
		}
		return MODEL_MAPPER.map(source, targetClass);
	}

	/**
	 * 转换为列表
	 * 
	 * @param sourceList
	 *            源列表
	 * @param targetClass
	 *            目标类型
	 * @return
	 * @author 杨昌国 2017-12-01 16:21:48
	 */
	public static <TSource, Target> List<Target> mapList(Collection<TSource> sourceList, Class<Target> targetClass) {
		return mapList(sourceList, targetClass, null);
	}

	/**
	 * 转换为列表
	 * 
	 * @param sourceList
	 * @param targetClass
	 * @param setAction
	 * @return
	 */
	public static <TSource, Target> List<Target> mapList(Collection<TSource> sourceList, Class<Target> targetClass,
			FunctionTwoAction<TSource, Target> setAction) {
		List<Target> items = new ArrayList<Target>();
		if (sourceList == null) {
			return items;
		}
		FunctionTwoAction<TSource, Target> act = setAction;
		if (act != null) {
			for (TSource source : sourceList) {
				Target item = map(source, targetClass);
				act.apply(source, item);
				items.add(item);
			}
		} else {
			for (TSource source : sourceList) {
				Target item = map(source, targetClass);
				items.add(item);
			}
		}
		return items;
	}

	/**
	 * 转换
	 * 
	 * @param source
	 *            源
	 * @param targetClass
	 *            目标类型
	 * @param typeMapName
	 * @return
	 */
	public <Target> Target map(Object source, Class<Target> targetClass, String typeMapName) {
		if (source == null) {
			return null;
		}
		return MODEL_MAPPER.map(source, targetClass, typeMapName);
	}

	/**
	 * 添加转换
	 * 
	 * @param converter
	 *            转换器
	 */
	public static <S, D> void addConverter(Converter<S, D> converter) {
		MODEL_MAPPER.addConverter(converter);
	}

	/**
	 * 添加映射
	 * 
	 * @param propertyMap
	 * @return
	 */
	public <S, D> TypeMap<S, D> addMappings(PropertyMap<S, D> propertyMap) {
		return MODEL_MAPPER.addMappings(propertyMap);
	}

}
